package com.budwk.app.sqfwV2.component;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.common.config.AppException;
import com.budwk.app.oss.models.SysOss;
import com.budwk.app.sqfw.component.CommonComponent;
import com.budwk.app.sqfw.component.FromSummaryComponent;
import com.budwk.app.sqfw.enums.SupportBusinessTypeEnum;
import com.budwk.app.sqfw.models.SqfwDownFileRecordLog;
import com.budwk.app.sqfw.models.Sqfw_completeflow;
import com.budwk.app.sqfw.services.SqfwCompleteflowService;
import com.budwk.app.sqfw.services.SqfwDownRecordlogService;
import com.budwk.app.sqfw.vo.GenerateExcelUrlVO;
import com.budwk.app.sqfw.vo.GenerateWordAndPdfUrlVO;
import com.budwk.app.sqfwDoc.bo.ExcelCreateConfig;
import com.budwk.app.sqfwDoc.codeGenerator.pdfGenerate.AbstractCustomerPdfCreateField;
import com.budwk.app.sqfwDoc.codeGenerator.pdfGenerate.BaseTemplatePdfGenerator;
import com.budwk.app.sqfwDoc.codeGenerator.pdfGenerate.SqfwPdfCreateCommonBO;
import com.budwk.app.sqfwDoc.codeGeneratorV2.fileParam.PdfGenerateParam;
import com.budwk.app.sqfwDoc.codeGeneratorV2.generate.BasePdfGenerator;
import com.budwk.app.sqfwDoc.codeGeneratorV2.generate.ResultOfPdfGenerator;
import com.budwk.app.sqfwV2.dto.dto.dayingRoad.DownExcelLedgerReqVo;
import com.budwk.app.sqfwV2.dto.dto.dayingRoad.DownFileTypesResVo;
import com.budwk.app.sqfwV2.dto.vo.DocumentDownVo;
import com.budwk.app.sqfwV2.enums.DayingRoadFileServiceEnum;
import com.budwk.app.sqfwV2.enums.FileServiceConfigEnum;
import com.budwk.app.sqfwV2.enums.publicSecurity.PublicSecurityFileEnum;
import com.budwk.app.util.StrUtil;
import com.budwk.app.util.poiUtils.CommonFormOfficeUtils;
import com.budwk.app.util.poiUtils.nutzBeanUtils.NutzIocUtils;
import com.budwk.starter.common.result.Result;
import com.budwk.starter.security.utils.SecurityUtil;
import com.deepoove.poi.XWPFTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Cnd;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文档下载业务公共类
 */

@Slf4j
public class DocumentDownComponent {

    /**
     * 批量下载下载pdf 主要从工作流表中下载
     *
     * 传值 工作流id
     */
    public static DownFileTypesResVo batchDownPdfFile(DownExcelLedgerReqVo reqVo) {
        reqVo.setFileName(getFileName(reqVo.getFileType(), reqVo.getFileCode()));
        return downPdfFile(reqVo);
    }


    private static String getFileName(String fillType, String fileCode) {
        FileServiceConfigEnum e = FileServiceConfigEnum.findByCode(fillType, fileCode);
        if (e != null) {
            return e.getFileName();
        }
        // 如果是社会治安
        PublicSecurityFileEnum securityFileEnum = PublicSecurityFileEnum.getByCode(fileCode);
        if (securityFileEnum != null) {
            return securityFileEnum.getName();
        }
        return fillType;
    }

    /**
     * 下载word模板
     * @return
     * @throws IOException
     */
    public static DownFileTypesResVo downWordDocTemplate(DocumentDownVo documentDownVo) {
        return downDoc(documentDownVo);
    }

    /**
     * 下载word文件
     * @return
     * @throws IOException
     */
    public static DownFileTypesResVo downWordDocFile(DocumentDownVo documentDownVo) {
        return downDoc(documentDownVo);
    }

    /**
     * 下载excel模板 公共代码实现
     */
    public static DownFileTypesResVo downExcelTemplateFile(DownExcelLedgerReqVo reqVo) {
        return downExcelTemplate(reqVo);
    }

    /**
     * 对华为云下载的url做返回组装全路径处理
     * @param url
     * @return
     */
    public static String handleUrl(String url) {
        if (url.startsWith("/")) {
            // 组装华为云路径返回
            return String.format("%s%s", url, "?AccessKeyId=oss");
        }
        return url;
    }

    /**
     * 上传word空模板
     * @return
     */
    private static DownFileTypesResVo downDoc(DocumentDownVo documentDownVo) {
        try {
            DownExcelLedgerReqVo reqVo = documentDownVo.getReqVo();
            if (CollectionUtil.isEmpty(reqVo.getIds())) {
                throw new AppException("文档下载失败，请传递数据id！");
            }
            String fileName = String.format("%s%s", documentDownVo.getFileName(), reqVo.isDownTemplate() ? "模板" : "文档");
            boolean againGenerate = reqVo.isAgainGenerate();
            if (againGenerate) {
                return uploadDocTemplateFile(reqVo, documentDownVo, fileName);
            }
            // 从历史任务中获取
            DownFileTypesResVo f = checkFileExist(reqVo);
            if (f != null) {
                return f;
            }
            // 没有记录 重新下载
            return uploadDocTemplateFile(reqVo, documentDownVo, fileName);
        } catch (IOException e) {
            log.error("downDoc error: ", e);
            throw new AppException("数据下载失败，请联系管理员！");
        }
    }

    public static DownFileTypesResVo checkFileExist(DownExcelLedgerReqVo reqVo) {
        String entityId = String.join(",", reqVo.getIds());
        SqfwDownRecordlogService sqfwDownRecordlogService = NutzIocUtils.getBean(SqfwDownRecordlogService.class);
        SqfwDownFileRecordLog recordLog = sqfwDownRecordlogService.getUrlByEntityId(entityId);
        if (recordLog != null) {
            DownFileTypesResVo f = getDownFileTypesResVo(reqVo, recordLog.getUrl());
            f.setFileTemplatePath(recordLog.getUrl()).setFilePath(recordLog.getUrl());
            return f;
        }
        return null;
    }

    private static GenerateWordAndPdfUrlVO getBaseGenerateWordAndPdf(DocumentDownVo documentDownVo, String downFileName) throws IOException{
        BasePdfGenerator basePdfGenerator = documentDownVo.getBasePdfGenerator();
        if (basePdfGenerator != null) {
            ResultOfPdfGenerator pdfResult = basePdfGenerator.createPdf(documentDownVo.getPdfGenerateParam());
            ByteArrayOutputStream pdfOs = new ByteArrayOutputStream();
            if (pdfResult == null) {
                return null;
            }
            pdfResult.getPdfXWPFTemplate().write(pdfOs);
            return CommonFormOfficeUtils.wordUpload(pdfOs, downFileName, "");
        }
        return null;
    }
    private static GenerateWordAndPdfUrlVO getBaseTemGenerateWordAndPdf(DocumentDownVo documentDownVo, String downFileName) throws IOException{
        BaseTemplatePdfGenerator baseTemplatePdfGenerator = documentDownVo.getBaseTemplatePdfGenerator();
        if (baseTemplatePdfGenerator != null) {
            XWPFTemplate pdfTemplate = baseTemplatePdfGenerator.createPdf(documentDownVo.getSqfwPdfCreateCommonBO());
            ByteArrayOutputStream pdfOs = new ByteArrayOutputStream();
            if (pdfTemplate == null) {
                return null;
            }
            pdfTemplate.write(pdfOs);
            return CommonFormOfficeUtils.wordUpload(pdfOs, downFileName, "");
        }
        return null;
    }

    private static DownFileTypesResVo uploadDocTemplateFile(DownExcelLedgerReqVo reqVo, DocumentDownVo documentDownVo, String downFileName) throws IOException {
        log.info("uploadDocTemplateFile info documentDownVo : {}", JSONObject.toJSONString(documentDownVo));
        GenerateWordAndPdfUrlVO wordPdfResult = getBaseGenerateWordAndPdf(documentDownVo, downFileName);
        String entityId = CollectionUtil.isNotEmpty(reqVo.getIds()) ? String.join(",", reqVo.getIds()) : null;
        if (wordPdfResult == null) {
            wordPdfResult = getBaseTemGenerateWordAndPdf(documentDownVo, downFileName);
        }
        // 如果下载下来的数据还是空的话，就是下载失败
        if (wordPdfResult == null) {
            throw new AppException("文档下载失败！");
        }
        String url = handleUrl(wordPdfResult.getUrl());
        log.info("uploadDocTemplateFile: {}", NutzIocUtils.getOssPrefix() + url);
        DownFileTypesResVo fileTypesResVo = new DownFileTypesResVo();
        fileTypesResVo.setFileTemplatePath(url).setFilePath(url);
        fileTypesResVo.setFileType(reqVo.getFileType()).setFileCode(reqVo.getFileCode());
        // 3 记录下载日志
        String title = String.format("%s%s", downFileName, SecurityUtil.getUserId());
        CommonComponent.insertDownRecordLog(null, JSONObject.toJSONString(Result.data(wordPdfResult)),
                title, fileTypesResVo.getFileTemplatePath(), entityId);
        log.info("uploadDocTemplateFile info documentDownVo fileTypesResVo res: {}", JSONObject.toJSONString(fileTypesResVo));
        return fileTypesResVo;
    }


    private static DownFileTypesResVo downPdfFile(DownExcelLedgerReqVo reqVo) {
        if (CollectionUtil.isEmpty(reqVo.getIds())) {
            throw new AppException("请提供下载ids!");
        }
        if (reqVo.isAgainGenerate()) {
            return resDownPdfFile(reqVo);
        }
        // 1从历史任务中获取
        DownFileTypesResVo f = checkFileExist(reqVo);
        if (f != null) {
            return f;
        }
        return resDownPdfFile(reqVo);

    }

    private static DownFileTypesResVo resDownPdfFile(DownExcelLedgerReqVo reqVo) {
        SqfwCompleteflowService sqfwCompleteflowService = NutzIocUtils.getBean(SqfwCompleteflowService.class);
        List<Sqfw_completeflow> list = sqfwCompleteflowService.query(Cnd.where(Sqfw_completeflow::getId, "in", reqVo.getIds()));
        List<String> paths = list.stream().map(Sqfw_completeflow::getResourcePath).collect(Collectors.toList());
//        String pdfUrl = CommonFormOfficeUtils.createConvergePdfAndUpload(paths, reqVo.getFileType());
        String pdfUrl = CommonFormOfficeUtils.createConvergePdfAndUpload(paths, reqVo.getFileName());
        log.info("pdfdown File url:  {}", NutzIocUtils.getOssPrefix() + pdfUrl );
        // 3 记录下载日志
        CommonComponent.insertDownRecordLog(null, JSONObject.toJSONString(Result.data(pdfUrl)),
                String.format("%s%s", reqVo.getFileType(), SecurityUtil.getUserId()), pdfUrl, String.join(",", reqVo.getIds()));
        // 返回数据
        return getDownFileTypesResVo(reqVo, pdfUrl);
    }


    private static DownFileTypesResVo getDownFileTypesResVo(DownExcelLedgerReqVo reqVo, String url) {
        DownFileTypesResVo fileTypesResVo = new DownFileTypesResVo();
        fileTypesResVo.setFileType(reqVo.getFileType()).setFilePath(url).setFileCode(reqVo.getFileCode());
        return fileTypesResVo;
    }

    /***
     *
     * @param excelConfigList
     * @param userId
     * @param ids
     * @param res
     * @param dataType 数据来源  1 ：大营路安全排查   2：儿童探访
     * @return
     */
    public static List<ExcelCreateConfig> checkIsDownFile(List<ExcelCreateConfig> excelConfigList, String userId, String ids, List<GenerateExcelUrlVO> res, String dataType) {
        List<ExcelCreateConfig> excelCodes = new ArrayList<>();
        SqfwDownRecordlogService sqfwDownRecordlogService = NutzIocUtils.getBean(SqfwDownRecordlogService.class);
        for (ExcelCreateConfig e : excelConfigList) {
            String entityId = getEntityId(e, dataType, userId, ids);
            if (e.getIsAgainGenerate()) {
                excelCodes.add(e);
                continue;
            }
            SqfwDownFileRecordLog recordLog = sqfwDownRecordlogService.getUrlByEntityId(entityId);
            if (recordLog != null) {
                GenerateExcelUrlVO g = new GenerateExcelUrlVO();
                String url = recordLog.getUrl().startsWith("/") ? String.format("%s%s", NutzIocUtils.getOssPrefix(), recordLog.getUrl()) : recordLog.getUrl();
                log.info("dayyinglu downExcelLedger recordLog url: {}", url);
                g.setExcelUrl(url).setUrl(url).setFileIdentity(e.getFileIdentity());
                res.add(g);
                continue;
            }
            excelCodes.add(e);
        }
        return excelCodes;
    }

    private static String getEntityId(ExcelCreateConfig e, String dataType, String userId, String ids) {
        String temId = ids;
        // 大营路
        if ("1".equals(dataType)) {
            DayingRoadFileServiceEnum fileEnum = DayingRoadFileServiceEnum.getByCode(e.getFileIdentity());
            e.setFileName(fileEnum.getService().getDownloadFileName());
            temId = e.getOnlyGenerateTemplateFlag() ? fileEnum.getTemplateId() : temId;
        }
        // 儿童探访记录
        if ("2".equals(dataType)) {
            FileServiceConfigEnum fileEnum = FileServiceConfigEnum.findByCode(SupportBusinessTypeEnum.CHILDREN_VISITATION.getName(), e.getFileIdentity());
            e.setFileName(fileEnum.getFileName());
            temId = e.getOnlyGenerateTemplateFlag() ? fileEnum.getTemplateId() : temId;
        }
        return temId + e.getFileIdentity() + userId;
    }

    public static void addGenerateExcel(List<ExcelCreateConfig> createConfigs, List<GenerateExcelUrlVO> urlVOS, String userId, String dataType, String ids) {
        for (GenerateExcelUrlVO v : urlVOS) {
            if (StringUtils.isEmpty(v.getUrl())) {
                continue;
            }
            Optional<ExcelCreateConfig> first = createConfigs.stream().filter(e -> e.getFileIdentity().equals(v.getFileIdentity())).findFirst();
            ExcelCreateConfig e = first.get();
            String entityId = getEntityId(e, dataType, userId, ids);
            String url = v.getUrl().startsWith("/") ? String.format("%s%s", NutzIocUtils.getOssPrefix(), v.getUrl()) : v.getUrl();
            CommonComponent.insertDownRecordLog(null, JSONObject.toJSONString(Result.data(v)),e.getFileName(), url, entityId);
        }
    }

    /**
     * excel模板下载
     * @param reqVo
     * @return
     */
    private static DownFileTypesResVo downExcelTemplate(DownExcelLedgerReqVo reqVo) {
        List<String> ids = reqVo.getIds();
        // 1 检查历史中是否存在记录
        if (!reqVo.isAgainGenerate()) {
            DownFileTypesResVo d = DocumentDownComponent.checkFileExist(reqVo);
            if (d != null) {
                return d;
            }
        }
        // 2 重新下载
        SummarySafetyCommponent summarySafetyCommponent = NutzIocUtils.getBean(SummarySafetyCommponent.class);
        reqVo.setIds(new ArrayList<>()).setExcelCodes(List.of(reqVo.getFileCode())).setFileType(reqVo.getFileType());
        List<GenerateExcelUrlVO> result = summarySafetyCommponent.downExcel1(reqVo);
        if (CollectionUtil.isEmpty(result)) {
            result = summarySafetyCommponent.downExcel2(reqVo);
        }
        DownFileTypesResVo res = new DownFileTypesResVo();
        res.setFileType(reqVo.getFileType()).setFileCode(reqVo.getFileCode());
        if (CollectionUtil.isEmpty(result)) {
            return res;
        }
        GenerateExcelUrlVO g = result.get(0);
        res.setFileTemplatePath(g.getExcelUrl()).setFilePath(g.getUrl());
        // 3 记录下载日志
        CommonComponent.insertDownRecordLog(null, JSONObject.toJSONString(Result.data(res)),
                String.format("%s%s", reqVo.getFileType(), SecurityUtil.getUserId()), res.getFilePath(), String.join(",", ids));
        return res;
    }

    /**
     * 构建word模板下载参数
     * @param reqVo
     * @param serviceConfig
     * @return
     */
    public static DocumentDownVo buildWordTemplateParam(DownExcelLedgerReqVo reqVo, FileServiceConfigEnum serviceConfig) {
        try {
            // 属于pdf模板
            DocumentDownVo documentDownVo = new DocumentDownVo();
            Class<?> service = serviceConfig.getService();
            if (service != null) {
                try {
                    PdfGenerateParam pdfGenerateParam = FromSummaryComponent.initPdfGenerateParam();
                    AbstractCustomerPdfCreateField a = StrUtil.getNewClass(serviceConfig.getPdfEntityPath());
                    pdfGenerateParam.setAbstractCustomerPdfCreateField(a);
                    BasePdfGenerator basePdfGenerator = StrUtil.getNewClass(service);
                    documentDownVo.setBasePdfGenerator(basePdfGenerator);
                    documentDownVo.setPdfGenerateParam(pdfGenerateParam);
                } catch (Exception e) {
                    SqfwPdfCreateCommonBO pdfCreateCommonBO = FromSummaryComponent.initPdfSqfwPdfCreateCommonBOParam();
                    AbstractCustomerPdfCreateField a = StrUtil.getNewClass(serviceConfig.getPdfEntityPath());
                    pdfCreateCommonBO.setAbstractCustomerPdfCreateField(a);
                    BaseTemplatePdfGenerator baseTemplatePdfGenerator = StrUtil.getNewClass(service);
                    documentDownVo.setBaseTemplatePdfGenerator(baseTemplatePdfGenerator);
                    documentDownVo.setSqfwPdfCreateCommonBO(pdfCreateCommonBO);
                }
                // 初始化基本参数
                documentDownVo.setReqVo(reqVo).setFileName(serviceConfig.getFileName());
            }
            return documentDownVo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppException("数据异常！");
        }
    }

    /**
     * 模板路径存在方式下载
     * @param reqVo
     * @param serviceConfig
     * @return
     */
    public static DownFileTypesResVo templatePathExistDownMethod(DownExcelLedgerReqVo reqVo, FileServiceConfigEnum serviceConfig) {
        // 1 判断是否在历史文件中存在
        if (!reqVo.isAgainGenerate()) {
            DownFileTypesResVo d = DocumentDownComponent.checkFileExist(reqVo);
            if (d != null) {
                return d;
            }
        }
        // 2 重新下载
        String fileTemplatePath = serviceConfig.getTemplatePath();
        if (StringUtils.isEmpty(fileTemplatePath)) {
            return null;
        }
        DownFileTypesResVo resVo = new DownFileTypesResVo();
        File file = new File(CommonFormOfficeUtils.getTemplatePathByOS(fileTemplatePath));
        SysOss sysOss = CommonFormOfficeUtils.uploadFile(file, serviceConfig.getFileName() + ".docx");
        String url = DocumentDownComponent.handleUrl(CommonFormOfficeUtils.getFilePathFromUploadFileUrl(sysOss));
        resVo.setFilePath(url).setFileTemplatePath(url).setFileCode(serviceConfig.getCode()).setFileName(serviceConfig.getFileName());
        // 3 记录下载日志
        CommonComponent.insertDownRecordLog(null, JSONObject.toJSONString(Result.data(resVo)),
                String.format("%s%s", reqVo.getFileType(), SecurityUtil.getUserId()), resVo.getFilePath(), String.join(",", List.of(serviceConfig.getTemplateId())));
        return resVo;

    }
}
